﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;


namespace VPN.Querier
{
    public class UserHelper
    {
        private static PrincipalContext pc = new PrincipalContext(ContextType.Machine, Environment.MachineName);

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="groups"></param>
        /// <param name="password"></param>
        /// <param name="expireDate"></param>
        /// <param name="email"></param>
        public static void AddUser(string userName, string[] groups, string password, DateTime expireDate, string email)
        {
            UserPrincipal user = new UserPrincipal(pc, userName, password, false);
            //user.EmailAddress = email;
            user.AccountExpirationDate = expireDate;
            user.Enabled = true;
            user.PasswordNeverExpires = true;
            user.Description = string.Join(",", groups);
            user.Save();
            AddUserToGroup(user, groups);
            System.Web.HttpContext.Current.Cache.Remove("Users");
        }

        /// <summary>
        /// 添加用户到组
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="groups"></param>
        public static void AddUserToGroup(string userName, string[] groups)
        {
            UserPrincipal user = UserPrincipal.FindByIdentity(pc, userName);
            AddUserToGroup(user, groups);
        }

        /// <summary>
        /// 添加用户到组
        /// </summary>
        /// <param name="user"></param>
        /// <param name="groups"></param>
        public static void AddUserToGroup(UserPrincipal user, string[] groups)
        {
            if (user == null) return;

            GroupPrincipal gp;
            foreach (string g in groups)
            {
                gp = GroupPrincipal.FindByIdentity(pc, g);
                if (gp != null)
                {
                    if (!gp.Members.Contains(user))
                    {
                        gp.Members.Add(user);
                    }
                }
                gp.Save();
            }
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userName"></param>
        public static void DeleteUser(string userName)
        {
            UserPrincipal[] users = getUserFromCache(new string[] { userName });
            if (users.Length == 0)
                return;
            users[0].Delete();
        }

        /// <summary>
        /// 获取用户名
        /// </summary>
        /// <param name="sid"></param>
        /// <returns></returns>
        public static string GetUserName(string sid)
        {
            UserPrincipal[] users = getUserFromCacheBySID(new string[] { sid });
            if (users.Length == 0)
                return string.Format("[{0}]", sid);
            return users[0].Name;
        }

        /// <summary>
        /// 获取用户SID
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public static string GetUserSID(string userName)
        {
            UserPrincipal[] users = getUserFromCache(new string[] { userName });
            if (users.Length == 0)
                return string.Empty;
            return users[0].Sid.ToString();
        }

        /// <summary>
        /// 根据用户名获取用户
        /// </summary>
        /// <param name="userNames"></param>
        /// <returns></returns>
        public static UserPrincipal[] GetUserInfo(string[] userNames)
        {
            return getUserFromCache(userNames);
        }

        /// <summary>
        /// 根据用户SID获取用户
        /// </summary>
        /// <param name="sids"></param>
        /// <returns></returns>
        public static UserPrincipal[] GetUserInfoBySID(string[] sids)
        {
            return getUserFromCacheBySID(sids);
        }

        public static UserPrincipal[] GetAllUsers()
        {
            return getUserFromCache(new string[] { });
        }

        /// <summary>
        /// 更新用户
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="userName"></param>
        /// <param name="groups"></param>
        /// <param name="password"></param>
        public static void UpdateUser(string sid, string userName, string[] groups, string password,DateTime expireDate,bool enable)
        {
            UserPrincipal[] users = GetUserInfoBySID(new string[] { sid });
            if (users.Length == 0)
                return;

            UserPrincipal u = users[0];
            u.Name = userName;
            u.AccountExpirationDate = expireDate;
            u.Description = string.Join(",", groups);
            u.Enabled = enable;
            u.Save();
            if (!string.IsNullOrEmpty(password))
                u.SetPassword(password);
            GroupPrincipal og = GroupPrincipal.FindByIdentity(pc, u.GetGroups().First(a => a.Name.ToLower().StartsWith("q")).Name);
            og.Members.Remove(u);
            og.Save();
            AddUserToGroup(u.Name, groups);
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="oldPassword"></param>
        public static void ChangePassword(string userName, string password, string oldPassword)
        {
            UserPrincipal[] users = getUserFromCache(new string[] { userName });
            if (users.Length == 0)
                return;
            users[0].ChangePassword(oldPassword, password);
        }

        #region Privates
        private static UserPrincipal[] getUserFromCache(string[] userNames)
        {
            if (System.Web.HttpContext.Current.Cache["Users"] == null)
            {
                GroupPrincipal g = GroupPrincipal.FindByIdentity(pc, "VPN");
                System.Web.HttpContext.Current.Cache["Users"] = g.Members;
            }
            PrincipalCollection users = (PrincipalCollection)System.Web.HttpContext.Current.Cache["Users"];

            if (userNames.Length == 0)
                return users.Cast<UserPrincipal>().ToArray();

            userNames = userNames.Select(a => a.ToLower()).ToArray();
            string pname = pc.Name.ToLower();
            UserPrincipal[] s = users.Where(a => userNames.Contains(string.Format("{0}\\{1}", pname, a.Name).ToLower())).Cast<UserPrincipal>().ToArray();
            return s;
        }

        private static UserPrincipal[] getUserFromCacheBySID(string[] sids)
        {
            if (System.Web.HttpContext.Current.Cache["Users"] == null)
            {
                GroupPrincipal g = GroupPrincipal.FindByIdentity(pc, "VPN");
                System.Web.HttpContext.Current.Cache["Users"] = g.Members;
            }
            sids = sids.Select(a => a.ToLower()).ToArray();
            string pname = pc.Name.ToLower();
            PrincipalCollection users = (PrincipalCollection)System.Web.HttpContext.Current.Cache["Users"];
            UserPrincipal[] s = users.Where(a => sids.Contains(a.Sid.ToString().ToLower())).Cast<UserPrincipal>().ToArray();
            return s;
        }

        #endregion

    }
}
